// MODIFIED for ICCAVR
// Change Project->Options->Target to select your device, and
// change defines.h as needed
//
// richard@imagecraft.com 06/05/02
//
/*****************************************************************************
*
* Copyright (C) 1996-1998 Atmel Corporation
*
* File          : main.c
* Compiler      : IAR 1.51B
* Output size   : 505 bytes (size optimized)
* Created       : 16-jun-99
* Modified      : 5-jan-2000
* Last modified : 16-may-2001 by jll
*
* Support mail  : avr@atmel.com
*
* Description   : This Program allows an AVR with bootloader capabilities to 
*                 Read/write its own Flash/EEprom. To enter Programming mode   
*                 PD2 is checked, it this pin is pulled low, programming mode  
*                 is entered. If not, normal execution is done from $0000 
*                 "reset" vector in Application area.
*                 The PD2 pin should be pulled HIGH by an external Pull-up 
*                 resistor.
*
* Other info    : Code must be modified to use this specific code with devices
*                 other than ATmega161. Following change should be made:
*                    -Specify device in define list (e.g. _ATMEGA163)
*                 
*                 When using this code with (future) parts other than ATmega32,
*                 ATmega161 and ATmega163, it will be necessary to change more 
*                 than the device name. The changes that should be made is:
*                    -Device name
*                    -Device signature and memory settings (defines.h)
*                    -Device code
*                    -Linker file
*
*                 In general the linker file should always be verifyed to match
*                 the used part's boot address and size. Note that memory size
*                 is specified in bytes in the linker file.
****************************************************************************/
#include "config.h"
#include "defines.h"
#include "serial.h"
#include "flash.h"
#include "assembly.h"

void main(void)
{
    //void (*funcptr)( void ) = 0x0000;       // Set up function pointer   

    unsigned int intval,address,data;
    unsigned char val, ldata;

#ifdef _ATMEGA16
    UBRRL = (UART_UBRR_VALUE & 0xFF);                         // 19200bps @ 7.3728 MHz
    UCSRB = (1<<RXEN) | (1<<TXEN);      // Enable recieve and transmit
#endif

#ifdef _ATMEGA32
    UBRRL = 11;                         // 19200bps @ 3.69 MHz
    UCSRB = (1<<RXEN) | (1<<TXEN);      // Enable recieve and transmit UART1
#endif

#ifdef _ATMEGA161
    UBRR0 = 11;                          // 19200bps @ 3.69 MHz
    UCSR0B = (1<<RXEN0) | (1<<TXEN0);      // Enable recieve and transmit UART1
#endif

#ifdef _ATMEGA163
    UBRRL = 11;                          // 19200bps @ 3.69 MHz
    UCSRB = (1<<RXEN) | (1<<TXEN);        // Enable recieve and transmit
#endif

    PROGPORT |= PROGCTRL;               //enable pull-up on PROGCTRL line on PROGPORT
    if (PROGMODE)                       //If PROGPIN is pulled low: programmingmode. 
    {  
        for(;;)
        {
            val=recchar();

            if(val=='a')                    //Autoincrement?
            {
                sendchar('Y');				    //Autoincrement is quicker
            }

            else if(val=='A')                   //write address 
            {
                address=recchar();                //read address 8 MSB
                address=(address<<8)|recchar();
                address=address<<1;               //convert from word address to byte address
                sendchar('\r');
            }

            else if(val=='c')                   //Write program memory, low byte
            {
                ldata=recchar();
                sendchar('\r');
            }

            else if(val== 'C')                  //Write program memory, high byte 
            {
                data=ldata|(recchar()<<8);
                _WAIT_FOR_SPM();
                fill_temp_buffer(data,(address)); //call asm routine. 
                address+=2;  
                sendchar('\r');
            }

            else if(val=='e')                   //Chip erase 
            {
                for(address=0;address < APP_END;address += PAGESIZE)  //Application section = 60 pages
                {
                    _WAIT_FOR_SPM();
                    write_page(address,0x03);       //Perform page erase
                }
                sendchar('\r');        
            }

            else if(val=='l')                   // write lockbits 
            {
                _WAIT_FOR_SPM();
                write_lock_bits(recchar());
                sendchar('\r');
            }

            else if(val== 'm')                  // write page
            {
                _WAIT_FOR_SPM();
                write_page((address),0x05);       
                sendchar('\r');
            }

            else if((val=='P')||(val=='L'))     // Enter programming mode 
            {
                sendchar('\r');
            }

            else if (val=='p')			// Return programmer type 
            {
                sendchar('S');
            }

            else if(val=='R')                   //Read program memory 
            {
                _WAIT_FOR_SPM();
                write_page(0,0x11);       //Enable RWW Section
                intval=read_program_memory(address,0x00);
                sendchar((char)(intval>>8));      //send MSB  
                sendchar((char)intval);           //send LSB
                address+=2;  
            }

            else if (val == 'D')		// Write data memory(EEPROM)
            {
                _WAIT_FOR_SPM();
                EEARL = address;
                EEARH = (address >> 8);
                address++;
                EEDR = recchar();
                EECR |= (1<<EEMWE);
                EECR |= (1<<EEWE);
                while (EECR & (1<<EEWE))
                ;
                sendchar('\r');
            }

            else if (val == 'd')			// Read data memory(EEPROM)
            {
                EEARL = address;
                EEARH = (address >> 8);
                address++;
                EECR |= (1<<EERE);
                sendchar(EEDR);
            }

            else if(val=='F')                   // read fuse bits
            {
                _WAIT_FOR_SPM();
                sendchar(read_program_memory(0x0000,0x09));
            }        
            else if(val=='f')                   // Write fuse bits
            {
            }

            else if(val=='r')                   // read lock bits
            {
                _WAIT_FOR_SPM();
                sendchar(read_program_memory(0x0001,0x09));
            }

            else if(val=='N')                   // read high fuse bits
            {
                _WAIT_FOR_SPM();
                sendchar(read_program_memory(0x0003,0x09));
            }

            else if(val=='t')                   // Return supported device codes 
            {
                sendchar(PARTCODE);
                sendchar(0);
            }

            else if ((val=='x')||(val=='y')||(val=='T'))
            {
                recchar();
                sendchar('\r');
            }

            else if (val=='S')                  // Return software identifier 
            {
                sendchar('A');
                sendchar('V');
                sendchar('R');
                sendchar('B');
                sendchar('O');
                sendchar('O');
                sendchar('T');
            }

            else if (val=='V')                  // Return Software Version
            {
                sendchar('1');
                sendchar('0');
            }

            else if (val=='v')                  // Return Hardware Version
            {
                sendchar('1');
                sendchar('0');
            }

            else if (val=='s')                  // Read Signature Byte
            {	
                sendchar(sig_byte3);
                sendchar(sig_byte2);
                sendchar(sig_byte1);
            }

            else if(val!=0x1b)                  // if not esc
            {
                sendchar('?');
            }
        }
    }
    else
    {
        _WAIT_FOR_SPM();
        write_page(0,0x11);       //Enable RWW Section
        asm("CALL 0x00000000");
        //funcptr();        					// Jump to Reset vector 0x0000 in Application Section
    }
}
